﻿# coding: utf-8

import wx
import wx.lib.agw.genericmessagedialog as GMD

import Entity
import Camera
import Transformation
import SceneNode
import Engine

from Editor.InputHandler import CInputHandler
from Editor.History.CmdAddModel import CCmdAddModel

class CBuilderSingle(CInputHandler):
    """ The BuilderSingle is used to add object to scene one by one """
    
    def __init__(self):
        """ Default class constructor """
        
        CInputHandler.__init__(self)
        
        self._rotationRange = (0, 0)
        self._scaleRange = (0, 0)
        self._nodeRef = None
        self._nodeType = None
        
    def OnEnter(self, **p):
        PANEL_PROPERTY.SetPanelProperty(PANEL_PROP_BUILD_SINGLE)
        
    def OnExit(self):
        if self._nodeRef:
            node = self._nodeRef()
            if node:
                SCENE_EDITOR.RemoveSceneNode(node)
                
        self._nodeType = None        
        
    def SetRotationRange(self, range):
        """
        Set rotation range
        
        Parameters:
        @param range - the rotation range (min, max)
        """
        
        self._rotStart = start
        self._rotEnd = end
    
    def SetScaleRange(self, range):
        """
        Set scale range
        
        Parameters:
        @range - the scale range (min, max)
        """
        
        self._scaleStart = start
        self._scaleEnd = end
        
    def SetModelObject(self, fileName):
        """
        Set model object to build
        
        Parameters:
        @param fileName - the file path for the model object
        """
        
        if self._nodeRef:
            node = self._nodeRef()
            if node:
                SCENE_EDITOR.RemoveSceneNode(node)
                
        self._nodeRef, entityHandle = SCENE_EDITOR.CreateModelSceneNode(fileName, False)
        
        if not self._nodeRef:
            dlg = GMD.GenericMessageDialog(self, TD.ERR_LOAD_FILE_FAILED, TD.ERROR, wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return
            
        self._nodeType = Entity.ET_MODEL
        
    def SetWaterObject(self, gridSize, width, height, shaderFile, bumpTextureFile):
        """
        Set water object to build
        
        Parameters:
        @param gridSize - the mesh grid size of the water object.
        @param width - the width of the water object.
        @param height - the height of the water object.
        @param shaderFile - the shader file name which used for the water rendering.
        @param bumpTextureFile - the bump texture used for water rendering.
        """
        
        self._nodeRef, entityHandle = SCENE_EDITOR.CreateWaterSceneNode(gridSize, width, height, shaderFile, bumpTextureFile, False)

        if not self._nodeRef:
            dlg = GMD.GenericMessageDialog(self, TD.ERR_CREATE_WATER_REGION_FAILED, TD.ERROR, wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return
            
        self._nodeType = Entity.ET_WATER

    def OnMouseMotion(self,	e):
        """ Process mouse move message """

        if not self._nodeRef:
            return
        	
        node = self._nodeRef()
        if not node:
            return
        	
        x, y = e.GetPosition()
        
        width, height = PANEL_EDITOR_SCENE.GetSizeTuple()
        x0, y0, z0, nx, ny, nz = Camera.GetPickRay(Engine.GetCurrentCamera(), x, y, width, height)
        ix = -y0 / ny *	nx + x0
        iz = -y0 / ny *	nz + z0
        Transformation.SetRelativeTranslation(SceneNode._CTransformation(node.GetCoreHandle()), ix, 0, iz)
        
    def OnMouseLeftDown(self, e):
        """ Process mouse left down message """
        
        if not self._nodeRef:
            return
            
        node = self._nodeRef()
        if not node:
            return
        
        if self._nodeType == Entity.ET_MODEL:
            x, y, z = Transformation.GetRelativeTranslation(SceneNode._CTransformation(node.GetCoreHandle()))
            rx, ry, rz, rw = Transformation.GetRelativeRotation(SceneNode._CTransformation(node.GetCoreHandle()))
            sx, sy, sz = Transformation.GetRelativeScale(SceneNode._CTransformation(node.GetCoreHandle()))
            cmd = CCmdAddModel(fileName = node._fileName, translation = (x, y, z), rotation = (rx, ry, rz, rw), scaling = (sx, sy, sz))
            HISTORY_MANAGER.RunCommand(cmd)
        elif self._nodeType == Entity.ET_WATER:
            x, y, z = Transformation.GetRelativeTranslation(SceneNode._CTransformation(node.GetCoreHandle()))
            rx, ry, rz, rw = Transformation.GetRelativeRotation(SceneNode._CTransformation(node.GetCoreHandle()))
            nodeRef, entityHandle = SCENE_EDITOR.CreateWaterSceneNode(node._waterGridSize, node._waterWidth, node._waterHeight, node._waterShaderFile, node._waterBumpTextureFile, True)
            waterNode = nodeRef()
            Transformation.SetRelativeTranslation(SceneNode._CTransformation(waterNode.GetCoreHandle()), x, y, z)
            Transformation.SetRelativeRotation(SceneNode._CTransformation(waterNode.GetCoreHandle()), rx, ry, rz, rw)            
            
    def OnMouseRightDown(self, e):
        WORLD_EDITOR.ChangeCurrentOperate(OPD.OP_SELECT)
			
__builtins__['BUILDER_SINGLE'] = CBuilderSingle()